home *** CD-ROM | disk | FTP | other *** search
/ Aminet 44 / Aminet 44 (2001)(GTI - Schatztruhe)[!][Aug 2001].iso / Aminet / dev / misc / AmigaSDLsrc.lha / amisrc / SDL_joystick.c < prev    next >
C/C++ Source or Header  |  2001-04-29  |  13KB  |  583 lines

  1. /*
  2.     SDL - Simple DirectMedia Layer
  3.     Copyright (C) 1997, 1998, 1999, 2000, 2001  Sam Lantinga
  4.  
  5.     This library is free software; you can redistribute it and/or
  6.     modify it under the terms of the GNU Library General Public
  7.     License as published by the Free Software Foundation; either
  8.     version 2 of the License, or (at your option) any later version.
  9.  
  10.     This library is distributed in the hope that it will be useful,
  11.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  13.     Library General Public License for more details.
  14.  
  15.     You should have received a copy of the GNU Library General Public
  16.     License along with this library; if not, write to the Free
  17.     Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  18.  
  19.     Sam Lantinga
  20.     slouken@devolution.com
  21. */
  22.  
  23. #ifdef SAVE_RCSID
  24. static char rcsid =
  25.  "@(#) $Id: SDL_joystick.c,v 1.1.2.21 2001/02/10 07:20:04 hercules Exp $";
  26. #endif
  27.  
  28. /* This is the joystick API for Simple DirectMedia Layer */
  29.  
  30. #include <stdio.h>
  31. #include <stdlib.h>
  32. #include <string.h>
  33.  
  34. #include "SDL_error.h"
  35. #include "SDL_events.h"
  36. #ifndef DISABLE_EVENTS
  37. #include "SDL_events_c.h"
  38. #endif
  39. #include "SDL_joystick_c.h"
  40. #include "SDL_sysjoystick.h"
  41.  
  42. /* This is used for Quake III Arena */
  43. #ifdef DISABLE_EVENTS
  44. #define SDL_Lock_EventThread()
  45. #define SDL_Unlock_EventThread()
  46. #endif
  47.  
  48. Uint8 SDL_numjoysticks = 0;
  49. SDL_Joystick **SDL_joysticks = NULL;
  50. static SDL_Joystick *default_joystick = NULL;
  51.  
  52. int SDL_JoystickInit(void)
  53. {
  54.     int arraylen;
  55.     int status;
  56.  
  57.     SDL_numjoysticks = 0;
  58.     status = SDL_SYS_JoystickInit();
  59.     if ( status >= 0 ) {
  60.         arraylen = (status+1)*sizeof(*SDL_joysticks);
  61.         SDL_joysticks = (SDL_Joystick **)malloc(arraylen);
  62.         if ( SDL_joysticks == NULL ) {
  63.             SDL_numjoysticks = 0;
  64.         } else {
  65.             memset(SDL_joysticks, 0, arraylen);
  66.         }
  67.         SDL_numjoysticks = status;
  68.         status = 0;
  69.     }
  70.     default_joystick = NULL;
  71.     return(status);
  72. }
  73.  
  74. /*
  75.  * Count the number of joysticks attached to the system
  76.  */
  77. int SDL_NumJoysticks(void)
  78. {
  79.     return SDL_numjoysticks;
  80. }
  81.  
  82. /*
  83.  * Get the implementation dependent name of a joystick
  84.  */
  85. const char *SDL_JoystickName(int device_index)
  86. {
  87.     if ( (device_index < 0) || (device_index >= SDL_numjoysticks) ) {
  88.         SDL_SetError("There are %d joysticks available",
  89.                      SDL_numjoysticks);
  90.         return(NULL);
  91.     }
  92.     return(SDL_SYS_JoystickName(device_index));
  93. }
  94.  
  95. /*
  96.  * Open a joystick for use - the index passed as an argument refers to
  97.  * the N'th joystick on the system.  This index is the value which will
  98.  * identify this joystick in future joystick events.
  99.  *
  100.  * This function returns a joystick identifier, or NULL if an error occurred.
  101.  */
  102. SDL_Joystick *SDL_JoystickOpen(int device_index)
  103. {
  104.     int i;
  105.     SDL_Joystick *joystick;
  106.  
  107.     if ( (device_index < 0) || (device_index >= SDL_numjoysticks) ) {
  108.         SDL_SetError("There are %d joysticks available",
  109.                      SDL_numjoysticks);
  110.         return(NULL);
  111.     }
  112.  
  113.     /* If the joystick is already open, return it */
  114.     for ( i=0; SDL_joysticks[i]; ++i ) {
  115.         if ( device_index == SDL_joysticks[i]->index ) {
  116.             joystick = SDL_joysticks[i];
  117.             ++joystick->ref_count;
  118.             return(joystick);
  119.         }
  120.     }
  121.  
  122.     /* Create and initialize the joystick */
  123.     joystick = (SDL_Joystick *)malloc((sizeof *joystick));
  124.     if ( joystick != NULL ) {
  125.         memset(joystick, 0, (sizeof *joystick));
  126.         joystick->index = device_index;
  127.         if ( SDL_SYS_JoystickOpen(joystick) < 0 ) {
  128.             free(joystick);
  129.             joystick = NULL;
  130.         } else {
  131.             if ( joystick->naxes > 0 ) {
  132.                 joystick->axes = (Sint16 *)malloc
  133.                     (joystick->naxes*sizeof(Sint16));
  134.             }
  135.             if ( joystick->nhats > 0 ) {
  136.                 joystick->hats = (Uint8 *)malloc
  137.                     (joystick->nhats*sizeof(Uint8));
  138.             }
  139.             if ( joystick->nballs > 0 ) {
  140.                 joystick->balls = (struct balldelta *)malloc
  141.                   (joystick->nballs*sizeof(*joystick->balls));
  142.             }
  143.             if ( joystick->nbuttons > 0 ) {
  144.                 joystick->buttons = (Uint8 *)malloc
  145.                     (joystick->nbuttons*sizeof(Uint8));
  146.             }
  147.             if ( ((joystick->naxes > 0) && !joystick->axes)
  148.               || ((joystick->nhats > 0) && !joystick->hats)
  149.               || ((joystick->nballs > 0) && !joystick->balls)
  150.               || ((joystick->nbuttons > 0) && !joystick->buttons)) {
  151.                 SDL_OutOfMemory();
  152.                 SDL_JoystickClose(joystick);
  153.                 joystick = NULL;
  154.             }
  155.             if ( joystick->axes ) {
  156.                 memset(joystick->axes, 0,
  157.                     joystick->naxes*sizeof(Sint16));
  158.             }
  159.             if ( joystick->hats ) {
  160.                 memset(joystick->hats, 0,
  161.                     joystick->nhats*sizeof(Uint8));
  162.             }
  163.             if ( joystick->balls ) {
  164.                 memset(joystick->balls, 0,
  165.                   joystick->nballs*sizeof(*joystick->balls));
  166.             }
  167.             if ( joystick->buttons ) {
  168.                 memset(joystick->buttons, 0,
  169.                     joystick->nbuttons*sizeof(Uint8));
  170.             }
  171.         }
  172.     }
  173.     if ( joystick ) {
  174.         /* Add joystick to list */
  175.         ++joystick->ref_count;
  176.         SDL_Lock_EventThread();
  177.         for ( i=0; SDL_joysticks[i]; ++i )
  178.             /* Skip to next joystick */;
  179.         SDL_joysticks[i] = joystick;
  180.         SDL_Unlock_EventThread();
  181.     }
  182.     return(joystick);
  183. }
  184.  
  185. /*
  186.  * Returns 1 if the joystick has been opened, or 0 if it has not.
  187.  */
  188. int SDL_JoystickOpened(int device_index)
  189. {
  190.     int i, opened;
  191.  
  192.     opened = 0;
  193.     for ( i=0; SDL_joysticks[i]; ++i ) {
  194.         if ( SDL_joysticks[i]->index == (Uint8)device_index ) {
  195.             opened = 1;
  196.             break;
  197.         }
  198.     }
  199.     return(opened);
  200. }
  201.  
  202. static int ValidJoystick(SDL_Joystick **joystick)
  203. {
  204.     int valid;
  205.  
  206.     if ( *joystick == NULL ) {
  207.         *joystick = default_joystick;
  208.     }
  209.     if ( *joystick == NULL ) {
  210.         SDL_SetError("Joystick hasn't been opened yet");
  211.         valid = 0;
  212.     } else {
  213.         valid = 1;
  214.     }
  215.     return valid;
  216. }
  217.  
  218. /*
  219.  * Get the device index of an opened joystick.
  220.  */
  221. int SDL_JoystickIndex(SDL_Joystick *joystick)
  222. {
  223.     if ( ! ValidJoystick(&joystick) ) {
  224.         return(-1);
  225.     }
  226.     return(joystick->index);
  227. }
  228.  
  229. /*
  230.  * Get the number of multi-dimensional axis controls on a joystick
  231.  */
  232. int SDL_JoystickNumAxes(SDL_Joystick *joystick)
  233. {
  234.     if ( ! ValidJoystick(&joystick) ) {
  235.         return(-1);
  236.     }
  237.     return(joystick->naxes);
  238. }
  239.  
  240. /*
  241.  * Get the number of hats on a joystick
  242.  */
  243. int SDL_JoystickNumHats(SDL_Joystick *joystick)
  244. {
  245.     if ( ! ValidJoystick(&joystick) ) {
  246.         return(-1);
  247.     }
  248.     return(joystick->nhats);
  249. }
  250.  
  251. /*
  252.  * Get the number of trackballs on a joystick
  253.  */
  254. int SDL_JoystickNumBalls(SDL_Joystick *joystick)
  255. {
  256.     if ( ! ValidJoystick(&joystick) ) {
  257.         return(-1);
  258.     }
  259.     return(joystick->nballs);
  260. }
  261.  
  262. /*
  263.  * Get the number of buttons on a joystick
  264.  */
  265. int SDL_JoystickNumButtons(SDL_Joystick *joystick)
  266. {
  267.     if ( ! ValidJoystick(&joystick) ) {
  268.         return(-1);
  269.     }
  270.     return(joystick->nbuttons);
  271. }
  272.  
  273. /*
  274.  * Get the current state of an axis control on a joystick
  275.  */
  276. Sint16 SDL_JoystickGetAxis(SDL_Joystick *joystick, int axis)
  277. {
  278.     Sint16 state;
  279.  
  280.     if ( ! ValidJoystick(&joystick) ) {
  281.         return(0);
  282.     }
  283.     if ( axis < joystick->naxes ) {
  284.         state = joystick->axes[axis];
  285.     } else {
  286.         SDL_SetError("Joystick only has %d axes", joystick->naxes);
  287.         state = 0;
  288.     }
  289.     return(state);
  290. }
  291.  
  292. /*
  293.  * Get the current state of a hat on a joystick
  294.  */
  295. Uint8 SDL_JoystickGetHat(SDL_Joystick *joystick, int hat)
  296. {
  297.     Uint8 state;
  298.  
  299.     if ( ! ValidJoystick(&joystick) ) {
  300.         return(0);
  301.     }
  302.     if ( hat < joystick->nhats ) {
  303.         state = joystick->hats[hat];
  304.     } else {
  305.         SDL_SetError("Joystick only has %d hats", joystick->nhats);
  306.         state = 0;
  307.     }
  308.     return(state);
  309. }
  310.  
  311. /*
  312.  * Get the ball axis change since the last poll
  313.  */
  314. int SDL_JoystickGetBall(SDL_Joystick *joystick, int ball, int *dx, int *dy)
  315. {
  316.     int retval;
  317.  
  318.     if ( ! ValidJoystick(&joystick) ) {
  319.         return(-1);
  320.     }
  321.  
  322.     retval = 0;
  323.     if ( ball < joystick->nballs ) {
  324.         if ( dx ) {
  325.             *dx = joystick->balls[ball].dx;
  326.         }
  327.         if ( dy ) {
  328.             *dy = joystick->balls[ball].dy;
  329.         }
  330.         joystick->balls[ball].dx = 0;
  331.         joystick->balls[ball].dy = 0;
  332.     } else {
  333.         SDL_SetError("Joystick only has %d balls", joystick->nballs);
  334.         retval = -1;
  335.     }
  336.     return(retval);
  337. }
  338.  
  339. /*
  340.  * Get the current state of a button on a joystick
  341.  */
  342. Uint8 SDL_JoystickGetButton(SDL_Joystick *joystick, int button)
  343. {
  344.     Uint8 state;
  345.  
  346.     if ( ! ValidJoystick(&joystick) ) {
  347.         return(0);
  348.     }
  349.     if ( button < joystick->nbuttons ) {
  350.         state = joystick->buttons[button];
  351.     } else {
  352.         SDL_SetError("Joystick only has %d buttons",joystick->nbuttons);
  353.         state = 0;
  354.     }
  355.     return(state);
  356. }
  357.  
  358. /*
  359.  * Close a joystick previously opened with SDL_JoystickOpen()
  360.  */
  361. void SDL_JoystickClose(SDL_Joystick *joystick)
  362. {
  363.     int i;
  364.  
  365.     if ( ! ValidJoystick(&joystick) ) {
  366.         return;
  367.     }
  368.  
  369.     /* First decrement ref count */
  370.     if ( --joystick->ref_count > 0 ) {
  371.         return;
  372.     }
  373.  
  374.     /* Lock the event queue - prevent joystick polling */
  375.     SDL_Lock_EventThread();
  376.  
  377.     if ( joystick == default_joystick ) {
  378.         default_joystick = NULL;
  379.     }
  380.     SDL_SYS_JoystickClose(joystick);
  381.  
  382.     /* Remove joystick from list */
  383.     for ( i=0; SDL_joysticks[i]; ++i ) {
  384.         if ( joystick == SDL_joysticks[i] ) {
  385.             memcpy(&SDL_joysticks[i], &SDL_joysticks[i+1],
  386.                    (SDL_numjoysticks-i)*sizeof(joystick));
  387.             break;
  388.         }
  389.     }
  390.  
  391.     /* Let the event thread keep running */
  392.     SDL_Unlock_EventThread();
  393.  
  394.     /* Free the data associated with this joystick */
  395.     if ( joystick->axes ) {
  396.         free(joystick->axes);
  397.     }
  398.     if ( joystick->hats ) {
  399.         free(joystick->hats);
  400.     }
  401.     if ( joystick->balls ) {
  402.         free(joystick->balls);
  403.     }
  404.     if ( joystick->buttons ) {
  405.         free(joystick->buttons);
  406.     }
  407.     free(joystick);
  408. }
  409.  
  410. void SDL_JoystickQuit(void)
  411. {
  412.     /* Stop the event polling */
  413.     SDL_Lock_EventThread();
  414.     SDL_numjoysticks = 0;
  415.     SDL_Unlock_EventThread();
  416.  
  417.     /* Quit the joystick setup */
  418.     SDL_SYS_JoystickQuit();
  419.     if ( SDL_joysticks ) {
  420.         free(SDL_joysticks);
  421.         SDL_joysticks = NULL;
  422.     }
  423. }
  424.  
  425.  
  426. /* These are global for SDL_sysjoystick.c and SDL_events.c */
  427.  
  428. int SDL_PrivateJoystickAxis(SDL_Joystick *joystick, Uint8 axis, Sint16 value)
  429. {
  430.     int posted;
  431.  
  432.     /* Update internal joystick state */
  433.     joystick->axes[axis] = value;
  434.  
  435.     /* Post the event, if desired */
  436.     posted = 0;
  437. #ifndef DISABLE_EVENTS
  438.     if ( SDL_ProcessEvents[SDL_JOYAXISMOTION] == SDL_ENABLE ) {
  439.         SDL_Event event;
  440.         event.type = SDL_JOYAXISMOTION;
  441.         event.jaxis.which = joystick->index;
  442.         event.jaxis.axis = axis;
  443.         event.jaxis.value = value;
  444.         if ( (SDL_EventOK == NULL) || (*SDL_EventOK)(&event) ) {
  445.             posted = 1;
  446.             SDL_PushEvent(&event);
  447.         }
  448.     }
  449. #endif /* !DISABLE_EVENTS */
  450.     return(posted);
  451. }
  452.  
  453. int SDL_PrivateJoystickHat(SDL_Joystick *joystick, Uint8 hat, Uint8 value)
  454. {
  455.     int posted;
  456.  
  457.     /* Update internal joystick state */
  458.     joystick->hats[hat] = value;
  459.  
  460.     /* Post the event, if desired */
  461.     posted = 0;
  462. #ifndef DISABLE_EVENTS
  463.     if ( SDL_ProcessEvents[SDL_JOYHATMOTION] == SDL_ENABLE ) {
  464.         SDL_Event event;
  465.         event.jhat.type = SDL_JOYHATMOTION;
  466.         event.jhat.which = joystick->index;
  467.         event.jhat.hat = hat;
  468.         event.jhat.value = value;
  469.         if ( (SDL_EventOK == NULL) || (*SDL_EventOK)(&event) ) {
  470.             posted = 1;
  471.             SDL_PushEvent(&event);
  472.         }
  473.     }
  474. #endif /* !DISABLE_EVENTS */
  475.     return(posted);
  476. }
  477.  
  478. int SDL_PrivateJoystickBall(SDL_Joystick *joystick, Uint8 ball,
  479.                     Sint16 xrel, Sint16 yrel)
  480. {
  481.     int posted;
  482.  
  483.     /* Update internal mouse state */
  484.     joystick->balls[ball].dx += xrel;
  485.     joystick->balls[ball].dy += yrel;
  486.  
  487.     /* Post the event, if desired */
  488.     posted = 0;
  489. #ifndef DISABLE_EVENTS
  490.     if ( SDL_ProcessEvents[SDL_JOYBALLMOTION] == SDL_ENABLE ) {
  491.         SDL_Event event;
  492.         event.jball.type = SDL_JOYBALLMOTION;
  493.         event.jball.which = joystick->index;
  494.         event.jball.ball = ball;
  495.         event.jball.xrel = xrel;
  496.         event.jball.yrel = yrel;
  497.         if ( (SDL_EventOK == NULL) || (*SDL_EventOK)(&event) ) {
  498.             posted = 1;
  499.             SDL_PushEvent(&event);
  500.         }
  501.     }
  502. #endif /* !DISABLE_EVENTS */
  503.     return(posted);
  504. }
  505.  
  506. int SDL_PrivateJoystickButton(SDL_Joystick *joystick, Uint8 button, Uint8 state)
  507. {
  508.     int posted;
  509. #ifndef DISABLE_EVENTS
  510.     SDL_Event event;
  511.  
  512.     switch ( state ) {
  513.         case SDL_PRESSED:
  514.             event.type = SDL_JOYBUTTONDOWN;
  515.             break;
  516.         case SDL_RELEASED:
  517.             event.type = SDL_JOYBUTTONUP;
  518.             break;
  519.         default:
  520.             /* Invalid state -- bail */
  521.             return(0);
  522.     }
  523. #endif /* !DISABLE_EVENTS */
  524.  
  525.     /* Update internal joystick state */
  526.     joystick->buttons[button] = state;
  527.  
  528.     /* Post the event, if desired */
  529.     posted = 0;
  530. #ifndef DISABLE_EVENTS
  531.     if ( SDL_ProcessEvents[event.type] == SDL_ENABLE ) {
  532.         event.jbutton.which = joystick->index;
  533.         event.jbutton.button = button;
  534.         event.jbutton.state = state;
  535.         if ( (SDL_EventOK == NULL) || (*SDL_EventOK)(&event) ) {
  536.             posted = 1;
  537.             SDL_PushEvent(&event);
  538.         }
  539.     }
  540. #endif /* !DISABLE_EVENTS */
  541.     return(posted);
  542. }
  543.  
  544. void SDL_JoystickUpdate(void)
  545. {
  546.     int i;
  547.  
  548.     for ( i=0; SDL_joysticks[i]; ++i ) {
  549.         SDL_SYS_JoystickUpdate(SDL_joysticks[i]);
  550.     }
  551. }
  552.  
  553. int SDL_JoystickEventState(int state)
  554. {
  555. #ifdef DISABLE_EVENTS
  556.     return SDL_IGNORE;
  557. #else
  558.     const Uint8 event_list[] = {
  559.         SDL_JOYAXISMOTION, SDL_JOYBALLMOTION, SDL_JOYHATMOTION,
  560.         SDL_JOYBUTTONDOWN, SDL_JOYBUTTONUP,
  561.     };
  562.     int i;
  563.  
  564.     switch (state) {
  565.         case SDL_QUERY:
  566.             state = SDL_IGNORE;
  567.             for ( i=0; i<SDL_TABLESIZE(event_list); ++i ) {
  568.                 state = SDL_EventState(event_list[i],SDL_QUERY);
  569.                 if ( state == SDL_ENABLE ) {
  570.                     break;
  571.                 }
  572.             }
  573.             break;
  574.         default:
  575.             for ( i=0; i<SDL_TABLESIZE(event_list); ++i ) {
  576.                 SDL_EventState(event_list[i], state);
  577.             }
  578.             break;
  579.     }
  580.     return(state);
  581. #endif /* DISABLE_EVENTS */
  582. }
  583.